﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TableParsers;

namespace SpeakupTests.WebLayer.ClassTypes
{
    [TestClass]
    public class ClassTimeTests
    {
        [TestMethod]
        public void CreateClassTime()
        {
            Random rnd = new Random();
            for (int i = 0; i < 10; i++)
            {
                DateTime date = DateTime.Now + new TimeSpan(rnd.Next(-10, 10), rnd.Next(0,23), rnd.Next(0, 59), rnd.Next(0, 59));
                ClassTime ct = new ClassTime(date, new TimeSpan(), new TimeSpan());

                Assert.AreEqual(date, ct.Date);
            }

            for (int i = 0; i < 10; i++)
            {
                TimeSpan begin = new TimeSpan(rnd.Next(0, 23), rnd.Next(0, 59), rnd.Next(0, 59));
                ClassTime ct = new ClassTime(DateTime.Now, begin, begin + new TimeSpan(1,0,0));

                Assert.AreEqual(begin, ct.Begin);
            }

            for (int i = 0; i < 10; i++)
            {
                TimeSpan end = new TimeSpan(rnd.Next(0, 23), rnd.Next(0, 59), rnd.Next(0, 59));
                ClassTime ct = new ClassTime(DateTime.Now, end - new TimeSpan(1, 0, 0), end);

                Assert.AreEqual(end, ct.End);
            }
        }

        [TestMethod]
        public void ClassTimeEqualsAsObject()
        {
            DateTime dateNow = DateTime.Now;

            //equality with null
            Object obj = new ClassTime(dateNow, new TimeSpan(), new TimeSpan());
            Assert.IsFalse(obj.Equals(null));

            //equality with other object
            int i = 10;
            Assert.IsFalse(obj.Equals(i));

            //equality with itself
            Assert.IsTrue(obj.Equals(obj));

            //all members are assigned the same values
            Object objLeft = new ClassTime(dateNow, new TimeSpan(1,0,0), new TimeSpan(2,0,0));
            Object objRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsTrue(objLeft.Equals(objRight));
            Assert.IsTrue(objRight.Equals(objLeft));

            //date is different
            objLeft = new ClassTime(dateNow                         , new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            objRight = new ClassTime(dateNow + new TimeSpan(1,0,0,0), new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(objLeft.Equals(objRight));
            Assert.IsFalse(objRight.Equals(objLeft));

            //Begein is different
            objLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            objRight = new ClassTime(dateNow, new TimeSpan(1, 30, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(objLeft.Equals(objRight));
            Assert.IsFalse(objRight.Equals(objLeft));

            //End are different
            objLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            objRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 30, 0));

            Assert.IsFalse(objLeft.Equals(objRight));
            Assert.IsFalse(objRight.Equals(objLeft));

        }

        [TestMethod]
        public void ClassTimeEquals()
        {
            DateTime dateNow = DateTime.Now;

            //equality with null
            ClassTime ct = new ClassTime(dateNow, new TimeSpan(), new TimeSpan());
            Assert.IsFalse(ct.Equals(null));

            //equality with itself
            Assert.IsTrue(ct.Equals(ct));

            //all members are assigned the same values
            ClassTime ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ClassTime ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsTrue(ctLeft.Equals(ctRight));
            Assert.IsTrue(ctRight.Equals(ctLeft));

            //date is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(ctLeft.Equals(ctRight));
            Assert.IsFalse(ctRight.Equals(ctLeft));

            //Begein is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 30, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(ctLeft.Equals(ctRight));
            Assert.IsFalse(ctRight.Equals(ctLeft));

            //End are different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 30, 0));

            Assert.IsFalse(ctLeft.Equals(ctRight));
            Assert.IsFalse(ctRight.Equals(ctLeft));
        }

        [TestMethod]
        public void ClassTimeGetHashCode()
        {
            DateTime dateNow = DateTime.Now;
            //all members are assigned the same values
            ClassTime ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ClassTime ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.AreEqual(ctLeft.GetHashCode(), ctRight.GetHashCode());
            
            //date is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.AreNotEqual(ctLeft.GetHashCode(), ctRight.GetHashCode());

            //Begein is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 30, 0), new TimeSpan(2, 0, 0));

            Assert.AreNotEqual(ctLeft.GetHashCode(), ctRight.GetHashCode());

            //End are different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 30, 0));

            Assert.AreNotEqual(ctLeft.GetHashCode(), ctRight.GetHashCode());

        }

        [TestMethod]
        public void ClassTimeCompareTo()
        {
            DateTime dateNow = DateTime.Now;
            
            //all members are assigned the same values
            ClassTime ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ClassTime ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.AreEqual(0, ctLeft.CompareTo(ctRight));
            Assert.AreEqual(0, ctRight.CompareTo(ctLeft));

            //date is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.AreEqual(Math.Sign(ctLeft.Date.CompareTo(ctRight.Date)),
                            Math.Sign(ctLeft.CompareTo(ctRight)) );

            Assert.AreEqual(Math.Sign(ctRight.Date.CompareTo(ctLeft.Date)),
                            Math.Sign(ctRight.CompareTo(ctLeft)));

            //Begin is different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 30, 0), new TimeSpan(2, 0, 0));

            Assert.AreEqual(Math.Sign(ctLeft.Begin.CompareTo(ctRight.Begin)),
                           Math.Sign(ctLeft.CompareTo(ctRight)));

            Assert.AreEqual(Math.Sign(ctRight.Begin.CompareTo(ctLeft.Begin)),
                            Math.Sign(ctRight.CompareTo(ctLeft)));

            //End are different
            ctLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            ctRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 30, 0));

            Assert.AreEqual(Math.Sign(ctLeft.End.CompareTo(ctRight.End)),
                            Math.Sign(ctLeft.CompareTo(ctRight)));

            Assert.AreEqual(Math.Sign(ctRight.End.CompareTo(ctLeft.End)),
                            Math.Sign(ctRight.CompareTo(ctLeft)));
        }

        [TestMethod]
        public void ClassTimeOperators()
        {
            DateTime dateNow = DateTime.Now;

            ClassTime cnLeft = null;
            ClassTime cnRight = null;

            Assert.IsTrue(cnLeft == cnRight);
            Assert.IsFalse(cnLeft != cnRight);

            cnLeft = null;
            cnRight = new ClassTime(dateNow, new TimeSpan(), new TimeSpan());

            Assert.IsFalse(cnLeft == cnRight);
            Assert.IsFalse(cnRight == cnLeft);
            Assert.IsTrue(cnLeft != cnRight);
            Assert.IsTrue(cnRight != cnLeft);

            //all members are assigned the same values
            cnLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            cnRight = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsTrue(cnLeft == cnRight);
            Assert.IsTrue(cnRight == cnLeft);

            Assert.IsFalse(cnLeft != cnRight);
            Assert.IsFalse(cnRight != cnLeft);

            Assert.IsFalse(cnLeft < cnRight);
            Assert.IsFalse(cnRight < cnLeft);

            Assert.IsTrue(cnLeft <= cnRight);
            Assert.IsTrue(cnRight <= cnLeft);

            Assert.IsFalse(cnLeft > cnRight);
            Assert.IsFalse(cnRight > cnLeft);

            Assert.IsTrue(cnLeft >= cnRight);
            Assert.IsTrue(cnRight >= cnLeft);
            
            //date is different
            cnLeft = new ClassTime(dateNow                            , new TimeSpan(1,0,0), new TimeSpan(2, 0, 0));
            cnRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(cnLeft == cnRight);
            Assert.IsFalse(cnRight == cnLeft);

            Assert.IsTrue(cnLeft != cnRight);
            Assert.IsTrue(cnRight != cnLeft);

            Assert.AreEqual(cnLeft.Date < cnRight.Date, cnLeft < cnRight);
            Assert.AreEqual(cnRight.Date < cnLeft.Date, cnRight < cnLeft);

            Assert.AreEqual(cnLeft.Date <= cnRight.Date, cnLeft <= cnRight);
            Assert.AreEqual(cnRight.Date <= cnLeft.Date, cnRight <= cnLeft);

            Assert.AreEqual(cnLeft.Date > cnRight.Date, cnLeft > cnRight);
            Assert.AreEqual(cnRight.Date > cnLeft.Date, cnRight > cnLeft);

            Assert.AreEqual(cnLeft.Date >= cnRight.Date, cnLeft >= cnRight);
            Assert.AreEqual(cnRight.Date >= cnLeft.Date, cnRight >= cnLeft);

            //Begin is different
            cnLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            cnRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 30, 0), new TimeSpan(2, 0, 0));

            Assert.IsFalse(cnLeft == cnRight);
            Assert.IsFalse(cnRight == cnLeft);

            Assert.IsTrue(cnLeft != cnRight);
            Assert.IsTrue(cnRight != cnLeft);

            Assert.AreEqual(cnLeft.Begin  < cnRight.Begin, cnLeft < cnRight);
            Assert.AreEqual(cnRight.Begin < cnLeft.Begin, cnRight < cnLeft);

            Assert.AreEqual(cnLeft.Begin  <= cnRight.Begin, cnLeft <= cnRight);
            Assert.AreEqual(cnRight.Begin <= cnLeft.Begin , cnRight <= cnLeft);

            Assert.AreEqual(cnLeft.Begin > cnRight.Begin, cnLeft > cnRight);
            Assert.AreEqual(cnRight.Begin >cnLeft.Begin, cnRight > cnLeft);

            Assert.AreEqual(cnLeft.Begin  >= cnRight.Begin, cnLeft >= cnRight);
            Assert.AreEqual(cnRight.Begin >= cnLeft.Begin,  cnRight >= cnLeft);

            //End are different
            cnLeft = new ClassTime(dateNow, new TimeSpan(1, 0, 0), new TimeSpan(2, 0, 0));
            cnRight = new ClassTime(dateNow + new TimeSpan(1, 0, 0, 0), new TimeSpan(1, 0, 0), new TimeSpan(2, 30, 0));

            Assert.IsFalse(cnLeft == cnRight);
            Assert.IsFalse(cnRight == cnLeft);

            Assert.IsTrue(cnLeft != cnRight);
            Assert.IsTrue(cnRight != cnLeft);

            Assert.AreEqual(cnLeft.End < cnRight.End, cnLeft < cnRight);
            Assert.AreEqual(cnRight.End< cnLeft.End, cnRight < cnLeft);

            Assert.AreEqual(cnLeft.End <= cnRight.End, cnLeft <= cnRight);
            Assert.AreEqual(cnRight.End <= cnLeft.End, cnRight <= cnLeft);

            Assert.AreEqual(cnLeft.End > cnRight.End, cnLeft > cnRight);
            Assert.AreEqual(cnRight.End > cnLeft.End, cnRight > cnLeft);

            Assert.AreEqual(cnLeft.End >= cnRight.End, cnLeft >= cnRight);
            Assert.AreEqual(cnRight.End >= cnLeft.End, cnRight >= cnLeft);
        }
    }
}
